﻿using System;
using System.Collections.Generic;
using System.Text;

namespace Barbar.UrlGuard.Dal.Persist {
  internal class BinaryFactory : IBinaryFactory<IndexEntry>, IBinaryFactory<RecordHeader>, IBinaryFactory<MonitoringCheck> {
    #region IBinaryFactory<IndexEntry> Members

    byte[] IBinaryFactory<IndexEntry>.GetBytes(IndexEntry instance) {
      if (instance == null)
        throw new ArgumentNullException("instance");

      byte[] buffer = new byte[IndexEntry.BINARY_SIZE];
      Buffer.BlockCopy(BitConverter.GetBytes(instance.FilePosition), 0, buffer, 0, 8);
      Buffer.BlockCopy(instance.RecordType.ToByteArray(), 0, buffer, 8, 16);
      return buffer;
    }

    IndexEntry IBinaryFactory<IndexEntry>.GetObject(byte[] bytes) {
      if (bytes == null)
        throw new ArgumentNullException("bytes");
      
      IndexEntry result = new IndexEntry();
      result.FilePosition = BitConverter.ToInt64(bytes, 0);

      byte[] uidArray = new byte[16];
      Buffer.BlockCopy(bytes, 8, uidArray, 0, 16);
      result.RecordType = new Guid(uidArray);
      return result;
    }

    #endregion

    #region IBinaryFactory<RecordHeader> Members

    byte[] IBinaryFactory<RecordHeader>.GetBytes(RecordHeader instance) {
      if (instance == null)
        throw new ArgumentNullException("instance");

      byte[] buffer = new byte[RecordHeader.BINARY_SIZE];
      Buffer.BlockCopy(instance.RecordType.ToByteArray(), 0, buffer, 0, 16);
      Buffer.BlockCopy(BitConverter.GetBytes(instance.NextRecordPosition), 0, buffer, 16, 8);
      Buffer.BlockCopy(BitConverter.GetBytes(instance.RecordSize), 0, buffer, 24, 4);
      Buffer.BlockCopy(BitConverter.GetBytes(instance.RecordsCount), 0, buffer, 28, 4);
      Buffer.BlockCopy(BitConverter.GetBytes(instance.ChunkSize), 0, buffer, 32, 4);
      return buffer;
    }

    RecordHeader IBinaryFactory<RecordHeader>.GetObject(byte[] bytes) {
      if (bytes == null)
        throw new ArgumentNullException("bytes");

      RecordHeader result = new RecordHeader();

      byte[] uidArray = new byte[16];
      Buffer.BlockCopy(bytes, 0, uidArray, 0, 16);
      result.RecordType = new Guid(uidArray);
      result.NextRecordPosition = BitConverter.ToInt64(bytes, 16);
      result.RecordSize = BitConverter.ToInt32(bytes, 24);
      result.RecordsCount = BitConverter.ToInt32(bytes, 28);
      result.ChunkSize = BitConverter.ToInt32(bytes, 32);
      return result;
    }

    #endregion

    #region IBinaryFactory<MonitoringCheck> Members

    byte[] IBinaryFactory<MonitoringCheck>.GetBytes(MonitoringCheck instance) {
      if (instance == null)
        throw new ArgumentNullException("instance");

      byte[] buffer = new byte[MonitoringCheck.BINARY_SIZE];
      Buffer.BlockCopy(BitConverter.GetBytes(instance.CheckDate.Ticks), 0, buffer, 0, 8);
      Buffer.BlockCopy(BitConverter.GetBytes(instance.RequestLength), 0, buffer, 8, 8);
      Buffer.BlockCopy(BitConverter.GetBytes(instance.StatusCode), 0, buffer, 16, 4);
      return buffer;
    }

    MonitoringCheck IBinaryFactory<MonitoringCheck>.GetObject(byte[] bytes) {
      if (bytes == null)
        throw new ArgumentNullException("bytes");
      MonitoringCheck result = new MonitoringCheck();
      result.CheckDate = new DateTime(BitConverter.ToInt64(bytes, 0));
      result.RequestLength = BitConverter.ToDouble(bytes, 8);
      result.StatusCode = BitConverter.ToInt32(bytes, 16);
      return result;
    }

    #endregion
  }
}
